package crmdna.common;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;
import com.googlecode.objectify.NotFoundException;

public class APIResponse implements Serializable {

	private static final long serialVersionUID = 1L;

	public enum Status {
		SUCCESS, ERROR_LOGIN_REQUIRED, ERROR_INVALID_USER, 
		ERROR_INSUFFICIENT_PERMISSION, ERROR_RESOURCE_NOT_FOUND, ERROR_RESOURCE_ALREADY_EXISTS, 
		ERROR_RESOURCE_NOT_FULLY_SPECIFIED, ERROR_RESOURCE_INCORRECT, ERROR_PRECONDITION_FAILED, 
		ERROR_UNHANDLED_EXCEPTION, ERROR_NOT_IMPLEMENTED, ERROR_INTERNAL, 
		ERROR_OPERATION_NOT_ALLOWED, PAYPAL_ERROR, ERROR_OVERFLOW
	}

	public Status statusCode;
	public String userFriendlyMessage;	
	public Object object;
	public StackTraceElement[] stackTraceElements;
	public List<StackTraceElementProp> stackTrace = new ArrayList<>();
	public Long processingTimeInMS;

	//TODO: remove this in the future
	public APIResponse(Status statusCode, Object object) {
		this.statusCode = statusCode;
		this.object = object;
	}

	public APIResponse() {
	}

	public APIResponse status(Status status) {
		this.statusCode = status;
		return this;
	}

	public APIResponse message(String userFriendlyMessage) {
		this.userFriendlyMessage = userFriendlyMessage;
		return this;
	}
	
	public APIResponse object(Object object) {
		this.object = object;
		return this;
	}
	
	public APIResponse processingTimeInMS(Long ms) {
		this.processingTimeInMS = ms;
		return this;
	}
			
	public APIResponse(Exception ex) {
		// this constructor will be removed after the introduction of the other
		// version
		if (ex instanceof APIException) {
			APIException apiException = (APIException) ex;
			statusCode = apiException.statusCode;
			userFriendlyMessage = apiException.userFriendlyMessage;
		} else if (ex instanceof NotFoundException) {
			statusCode = Status.ERROR_RESOURCE_NOT_FOUND;
			userFriendlyMessage = "Objectify not found exception";
		} else {
			statusCode = Status.ERROR_UNHANDLED_EXCEPTION;
			userFriendlyMessage = "Unhandled exception. Please inform the development team.";
		}

		object = "Stack trace: \n" + Utils.stackTraceToString(ex);
	}

	//TODO: remove this
	public APIResponse(Exception ex, Boolean showStackTrace, String client,
			HttpServletRequest req, String login) {

		String stackTrace = null;

		if (showStackTrace == null)
			showStackTrace = false;

		if (showStackTrace == true) {
			stackTrace = Utils.stackTraceToString(ex);
			object = "Stack trace: <br>" + stackTrace;
		}

		if (ex instanceof APIException) {
			APIException apiException = (APIException) ex;
			statusCode = apiException.statusCode;
			userFriendlyMessage = apiException.userFriendlyMessage;
		} else if (ex instanceof NotFoundException) {
			// TODO: remove NotFoundException in the future
			statusCode = Status.ERROR_RESOURCE_NOT_FOUND;
			userFriendlyMessage = "Objectify not found exception";
		} else {
			statusCode = Status.ERROR_UNHANDLED_EXCEPTION;
			userFriendlyMessage = ex.getMessage();
			Utils.sendAlertEmailToDevTeam(client, ex, req, login);
		}
	}
	
	public APIResponse setJsonResponse(HttpServletResponse res) throws IOException {
		
		res.setContentType("application/json");
		res.setCharacterEncoding("UTF-8");
		
		PrintWriter pw = res.getWriter();
		pw.println(new Gson().toJson(this));
		pw.close();
		
		return this;
	}
}
